#!/bin/bash

RRD_DIR=./rrd
IMG_DIR=./img
TMP_DIR=/tmp
IMG_SUFFIX=png

function parse_sar() 
{
	# return
	_START_TIME=
	_END_TIME=
	_STEP=
	_INTERFACE_NAME=()

	local in_file=$1
	local out_file=$2
	shift 2

	# get date
	local date=$(head -n 1 $in_file | grep -o "[[:digit:]][[:digit:]]/[[:digit:]][[:digit:]]/[[:digit:]][[:digit:]]")

	# get start time and step
	local i=0
	for time in $(sed -n 3,100p $in_file | cut -f 1 -d ' '| uniq | head -n 3) ; do
		eval $(date "+time_$i=%s" -d "$date $time")
		let i++
	done

	_START_TIME=$time_0
	_STEP=$(( time_1 - time_0 ))
	if (( time_2 - time_1 != time_1 - time_0 )) ; then
		echo "bad step in sar file $in_file" 1>&2
		exit 1
	fi

	# get interface name
	if ((MULTI_INTERFACE)) ; then
		_INTERFACE_NAME=( $(sed -n 4,100p $in_file | awk '{print $2}' | sed 's#/#_#g' | sort | uniq) )
	fi

	# echo $_START_TIME $_STEP
	mkdir -p "$(dirname "$out_file")"

	# generate rrdtool update data
	grep '^\([[:digit:]][[:digit:]]:\?\)\{3\}' $in_file | 
	awk -v step=$_STEP -v start_time=$_START_TIME -v cols="$*" -v multi=$MULTI_INTERFACE -v outfile="$out_file" '
BEGIN {
	col_num = split( cols, col_array );
}
{
	if( NR == 1 ) {
		first_name=$2
		for( i = 1; i <= col_num; i++ ) {
			for( j = 1; j <= NF; j++ ) {
				if( "" $j == "" col_array[i] ) {
					index_array[i] = j;
					break;
				}
			}
			if( 0 == index_array[i] ) { 
				print "can not found "  col_array[i] >> "/dev/stderr"
				exit 1
			}
		}
	} else {
		if( "" first_name == "" $2 )
			next;
		if( multi ) {
			gsub( "/", "_", $2 );
			out = outfile "_" $2;
		} else {
			out = outfile;
		}
		for( i = 1; i <= col_num; i++ ) {
			if( 1 == i )
				printf( "%d", start_time ) >> out
			printf( ":%s", $index_array[i] ) >> out
		}
		printf( "\n" ) >> out
	}
	if( "" pre_time != "" $1 ) {
		start_time += step;
		pre_time = $1
	}
}
'
	# get end time
	local out=$out_file
	((MULTI_INTERFACE)) && out=${out_file}_${_INTERFACE_NAME[0]}
	_END_TIME=$(tail -n 1 "$out" | grep -o '^[[:digit:]]\+')
	# echo $_END_TIME
}

# MULTI_INTERFACE=1
# parse_sar a ab  rxpck/s   txpck/s    rxkB/s    txkB/s   rxcmp/s   txcmp/s  rxmcst/s

# echo $_START_TIME $_END_TIME $_STEP
# echo ${_INTERFACE_NAME[*]}
# exit 0

function set_default()
{
	MULTI_INTERFACE=0
	COLORS=("#FF0000" "#0000FF" "#00FF00" "#FF00FF" "#FFFF00" "#000000" "#00FFFF" "#C0C0C0" "#FF8C00" "#8FBC8F")
	STYLES=(LINE1 LINE1 LINE1 LINE1 LINE1 LINE1 LINE1 LINE1 LINE1 LINE1 LINE1 LINE1 LINE1 LINE1 )
	RRD_GRAPH_OPT=" -X 0 "
}

function execute() {
	local in_file=$1
	local sar=$TMP_DIR/$MODULE_NAME.sar_text
	local rrd_update_base=$TMP_DIR/$MODULE_NAME.rrdupdate.data

	local rrd=$RRD_DIR/$MODULE_NAME.rrd
	local img=$IMG_DIR/$MODULE_NAME.$IMG_SUFFIX

	# generate sar text
	if [ -z "$REMOTE_HOST" ] ; then
		# eval "sar $SAR_OPT -f '$in_file' > $sar"
		cp -f $in_file $sar
	else
		env ssh -n $REMOTE_HOST "LANG=C sar $SAR_OPT -f '$in_file'" > $sar
	fi

	local cols=( ${SHOW_COLS[@]} )
	local col_names=( )
	for (( i = 0; i < ${#cols[*]}; i++ )) ; do
		v=${cols[$i]}
		v=${v//\//_}
		col_names[$i]=${v//%/}
	done

	rm -rf $rrd_update_base*
	# generate rrdtool update 
	parse_sar $sar $rrd_update_base ${cols[@]}

	for interface in "" ${_INTERFACE_NAME[@]} ; do
		if (( MULTI_INTERFACE )) ; then
			[ -z "$interface" ] && continue

			local rrd=$RRD_DIR/${MODULE_NAME}_$interface.rrd
			local img=$IMG_DIR/${MODULE_NAME}_$interface.$IMG_SUFFIX
			local rrd_update=${rrd_update_base}_$interface
		else
			local rrd=$RRD_DIR/${MODULE_NAME}.rrd
			local img=$IMG_DIR/${MODULE_NAME}.$IMG_SUFFIX
			local rrd_update=${rrd_update_base}
		fi

		rrd_create="create --start $_START_TIME --step $_STEP $rrd"
		for (( i = 0; i < ${#col_names[*]}; i++ )) ; do
			rrd_create+=" DS:${col_names[$i]}:GAUGE:$((_STEP * 5)):U:U"
			rrd_create+=" RRA:AVERAGE:0.5:1:$(( (_END_TIME - _START_TIME)/_STEP ))"
		done

		echo $rrd_create

		rrd_graph="graph $img --start $_START_TIME --end $_END_TIME --width 800 --height 300 $RRD_GRAPH_OPT \
			--title '$interface $TITLE [FROM $(date -d "1970-01-01 00:00:00 UTC + $_START_TIME sec") TO  $(date -d "1970-01-01 00:00:00 UTC + $_END_TIME sec")] ' "
		for (( i = 0; i < ${#col_names[*]}; i++ )) ; do
			rrd_graph+=" DEF:${col_names[$i]}=$rrd:${col_names[$i]}:AVERAGE ${STYLES[$i]}:${col_names[$i]}'${COLORS[$i]}':${cols[$i]} \
			GPRINT:${col_names[$i]}:AVERAGE:'AVERAGE\: %-13.2lf' \
			GPRINT:${col_names[$i]}:MAX:'MAX\: %-13.2lf' \
			GPRINT:${col_names[$i]}:MIN:'MIN\: %-13.2lf' \
			COMMENT:'\n'"
		done
		echo $rrd_graph


		rm -rf $rrd $img
		eval "rrdtool $rrd_create"
		awk '{print "update '$rrd'", $1}' $rrd_update | rrdtool -  >/dev/null
		eval "rrdtool $rrd_graph"
	done
}

####### define module here ######

# define show module example
function show_example()
{
	MODULE_NAME=example # must set
	TITLE=
	SAR_OPT= # must set
	SHOW_COLS=() # must set
	STYLES=()
	COLORS=()
	MULTI_INTERFACE=0
	RRD_GRAPH_OPT=""
}

show_vm_page()
{
	MODULE_NAME=vm_page
	TITLE="VM page in and page out"
	SAR_OPT="-B"
	SHOW_COLS=(pgpgin/s pgpgout/s)
	STYLES=(LINE1 LINE1)
	# COLORS=()
	# MULTI_INTERFACE=0
}

show_disk_rw()
{
	MODULE_NAME=disk_rw
	TITLE="disk write read"
	SAR_OPT="-d -p"
	SHOW_COLS=(rd_sec/s wr_sec/s)
	STYLES=(LINE1 LINE1)
	# COLORS=()
	MULTI_INTERFACE=1
}

show_disk_util()
{
	MODULE_NAME=disk_util
	TITLE="disk util"
	SAR_OPT="-d -p"
	SHOW_COLS=( %util )
	STYLES=(AREA)
	# COLORS=()
	MULTI_INTERFACE=1
}

show_net()
{
	MODULE_NAME=net
	TITLE="net in/out"
	SAR_OPT="-n DEV"
	SHOW_COLS=(rxkB/s txkB/s)
	SHOW_COLS=(rxbyt/s txbyt/s)
	STYLES=(LINE1 LINE1)
	# COLORS=()
	MULTI_INTERFACE=1
	RRD_GRAPH_OPT=""
}

show_load()
{
	MODULE_NAME=load
	TITLE="load"
	SAR_OPT="-q"
	SHOW_COLS=(ldavg-1 ldavg-5 ldavg-15)
	STYLES=(AREA LINE1 LINE2)
	# COLORS=()
	# MULTI_INTERFACE=0
}

show_mem()
{
	MODULE_NAME=mem
	TITLE="memory utilization statistics"
	SAR_OPT="-r"
	SHOW_COLS=(kbmemused kbmemfree kbcached)
	STYLES=(AREA STACK LINE1)
	# COLORS=()
	# MULTI_INTERFACE=0
	RRD_GRAPH_OPT=""
}

show_cpu()
{
	MODULE_NAME=cpu
	TITLE="CPU"
	SAR_OPT="-P ALL"
	SHOW_COLS=(%user %nice %system %iowait %steal %idle)
	STYLES=(AREA STACK STACK STACK STACK STACK STACK STACK STACK STACK STACK STACK )
	# COLORS=()
	MULTI_INTERFACE=1
}

usage()
{
	echo "$0 [-h hostname] sar_raw_file [vm_page disk_rw disk_util net load mem cpu]"
	exit 1
} >&2


###### main 
REMOTE_HOST=
while getopts "h:" opt; do 
	case $opt in
		h ) REMOTE_HOST=$OPTARG ;;
		*) usage ;;
	esac
done

shift $((OPTIND-1))
[ $# -lt 2 ] && usage

export LANG=C
sar_file=$1
shift

mkdir -p $RRD_DIR $IMG_DIR $TMP_DIR
for module in $@ ; do
	set_default
	eval show_$module
	execute $sar_file
done


